/*
 * Copyright (c) 2010, Katholieke Universiteit Leuven
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of the Katholieke Universiteit Leuven nor the names of
 *       its contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * @addtogroup reconfiguration
 * @{
 */
/**
 * @file
 * Header file for remote runtime control and introspection in LooCI. 
 * @author
 * Wouter Horré <wouter.horre@cs.kuleuven.be>
 */
#ifndef __LOOCI_RCI_REMOTE_H__
#define __LOOCI_RCI_REMOTE_H__

#ifdef WITH_COMMANDS_CLIENT

#include "net/peers.h"
#include "commands/commands_commands.h"
#include "commands/commands_private.h"
#include <stdbool.h>

#define MIN(a,b) ((a) < (b) ? (a) : (b))

/**
 * Execute a remote command prepared with one of the _pack methods.
 *
 * @param destination Peer id of the command destination.
 * @param buffer Pointer to the buffer that holds the command.
 * @param buflen The length of content in the buffer.
 *
 * @return 'true' if the command was sent successful, 'false' otherwise
 */
bool looci_rci_remote_execute(peer_id_t destination, void * buffer, u8_t buflen); 

/**
 * Wait for the reply to a command to arrive or until a given condition occurs.
 *
 * @param buf Pointer to a buffer where the reply will be copied to.
 * @param buflen Pointer to a variable holding the length of the buffer. 
 *               The variable will contain the length of the reply when the call 
 *               returns (because of the arrival of a reply). 
 *               The variable should be initialized to the maximum size 
 *               of the buffer.
 * @param condition Alternative condition that will cause the call to return.
 *
 * @hideinitializer
 */
#define LOOCI_RCI_REMOTE_WAIT_REPLY_UNTIL(buf, buflen, condition) \
  do { \
    PROCESS_WAIT_EVENT_UNTIL(ev==PROCESS_EVENT_CONTINUE || ev==looci_command_reply_event || (condition)); \
    if((condition)) break; \
    if(ev==looci_command_reply_event) { \
      *buflen = MIN(((struct looci_command_reply_event_data *)data)->len, *buflen); \
      memcpy(buf, ((struct looci_command_reply_event_data *)data)->reply, *buflen); \
      process_post(PROCESS_CURRENT(), PROCESS_EVENT_CONTINUE, NULL); \
    }\
  } while(ev!=PROCESS_EVENT_CONTINUE)

/**
 * Wait for the reply to a command to arrive.
 *
 * @param buf Pointer to a buffer where the reply will be copied to.
 * @param buflen Pointer to a variable holding the length of the buffer. 
 *               The variable will contain the length of the reply when the call 
 *               returns. The variable should be initialized to the maximum size 
 *               of the buffer.
 *
 * @hideinitializer
 */
#define LOOCI_RCI_REMOTE_WAIT_REPLY(buf, buflen) \
  do { \
    PROCESS_WAIT_EVENT_UNTIL(ev==PROCESS_EVENT_CONTINUE || ev==looci_command_reply_event ); \
    if(ev==looci_command_reply_event) { \
      *buflen = MIN(((struct looci_command_reply_event_data *)data)->len, *buflen); \
      memcpy(buf, ((struct looci_command_reply_event_data *)data)->reply, *buflen); \
      process_post(PROCESS_CURRENT(), PROCESS_EVENT_CONTINUE, NULL); \
    }\
  } while(ev!=PROCESS_EVENT_CONTINUE)

#endif // WITH_COMMANDS_CLIENT
#endif //__LOOCI_RCI_REMOTE_H__
/** @} */
